package com.mymarkdown.app.service.impl;

import cn.hutool.core.io.IoUtil;
import com.alibaba.fastjson.JSON;
import com.mymarkdown.app.common.annotation.SystemConfigChangeHandler;
import com.mymarkdown.app.common.constant.Constant;
import com.mymarkdown.app.common.enums.SystemSettingChangeEventEnum;
import com.mymarkdown.app.interfaces.HandlerSystemConfigChange;
import com.mymarkdown.app.model.UserSettingInfo;
import com.mymarkdown.app.service.ObserverSettingService;
import com.mymarkdown.app.service.SystemSettingService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @author zenglun
 * @date 2021/12/15 3:05 下午
 * @description: TODO
 */
@Slf4j
@Service
public class ObserverSettingServiceImpl implements ObserverSettingService {
    @Autowired
    private CacheManager cacheManager;

    private Cache cache;

    private Map<SystemSettingChangeEventEnum, HandlerSystemConfigChange> handlerSystemConfigChangeMap = new HashMap<>();

    @Autowired
    private ApplicationContext applicationContext;

    @Autowired
    private SystemSettingService systemSettingService;

    /**
     * 初始化方法，获取Cache缓存信息
     */
    @PostConstruct
    public void init() {
        cache = cacheManager.getCache(Constant.AllCacheKey.SAVE_SYSTEM_SETTING_CACHE_KEY);
        Map<String, HandlerSystemConfigChange> beansOfType = applicationContext.getBeansOfType(HandlerSystemConfigChange.class);
        //对其进行过滤设置,初始化操作
        handlerSystemConfigChangeMap = beansOfType.entrySet().stream().collect(Collectors.toMap(ent -> {
            HandlerSystemConfigChange value = ent.getValue();
            SystemConfigChangeHandler annotation = value.getClass().getAnnotation(SystemConfigChangeHandler.class);
            if (Objects.isNull(annotation)) {
                log.warn("[ObserverSettingServiceImpl]---[init],类:{},没有被SystemConfigChangeHandler注解标识", value.getClass());
                return null;
            }
            return annotation.value();
        }, Map.Entry::getValue));
    }

    /**
     * 监视这个对象的属性变化，并找到相应的处理方法处理这个属性的变化
     *
     * @param userSettingInfo
     */
    @Override
    public void observer(UserSettingInfo userSettingInfo) {

        //从缓存中拿去对象，如果缓存中没有，则从磁盘中拿去
        Field[] declaredFields = UserSettingInfo.class.getDeclaredFields();
        //比对那个属性发生了变化
        UserSettingInfo originalSettingInfo = systemSettingService.getOriginalInfo();

        Stream.of(declaredFields).forEach(field -> {
            try {
                field.setAccessible(true);
                SystemConfigChangeHandler annotation = field.getAnnotation(SystemConfigChangeHandler.class);
                if (Objects.isNull(annotation)) {
                    return;
                }
                Object originalVal = field.get(originalSettingInfo);
                Object newVal = field.get(userSettingInfo);
                if (!Objects.equals(originalVal, newVal)) {
                    //如果不相等,则
                    SystemSettingChangeEventEnum value = annotation.value();
                    //从Map中获取注册的相应的bean信息
                    HandlerSystemConfigChange handlerSystemConfigChange = handlerSystemConfigChangeMap.get(value);
                    Optional.ofNullable(handlerSystemConfigChange).ifPresent(handler -> {
                        try {
                            handler.handler(originalVal, newVal, field, originalSettingInfo, userSettingInfo);
                        } catch (Exception e) {
                            //TODO 处理改变时发生异常
                            e.printStackTrace();
                            log.error("[ObserverSettingServiceImpl]---[observer],处理系统参数改变发生异常,异常信息为:{}", e);
                            try {
                                handler.error(e);
                            } catch (Exception exception) {
                                exception.printStackTrace();
                                log.error("[ObserverSettingServiceImpl]---[observer],处理异常时发生错误,处理的异常为:{}, 异常信息为:{}", e, exception);
                            }
                        }
                    });
                    if (Objects.isNull(handlerSystemConfigChange)) {
                        //TODO 没有找到相应的处理改变函数
                        log.warn("[ObserverSettingServiceImpl]---[observer],未找到相应的系统改变参数处理方法,事件类型为{}", value);
                    }
                }
            } catch (IllegalAccessException e) {
                e.printStackTrace();
                log.error("[ObserverSettingServiceImpl]---[observer],发生异常,异常信息为:{}", e);
            } finally {
                field.setAccessible(false);
            }
        });

    }
}
